﻿using Microsoft.VisualBasic.Devices;
using Microsoft.VisualBasic.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WindowsStateService.Data;
using WindowsStateService.Manager;
using WindowsStateService.Monitor;

namespace WindowsStateService
{
    public partial class Service1 : ServiceBase
    {
        private DateTime last_write_time = DateTime.Now;
        private BackgroundWorker log_worker;
        private BackgroundWorker minitor_worker;
        private bool monitor_worker_running = true;
        private CacheManager _cacheManager;


        private bool log_worker_running = true;
        private string today_file;
        private bool stop_sleep = false;
        public Service1()
        {
            InitializeComponent();
            log_worker = new BackgroundWorker();
            minitor_worker = new BackgroundWorker();
            log_worker.DoWork += Worker_Log_DoWork;
            minitor_worker.DoWork += Minitor_worker_DoWork;
        }

        private void Minitor_worker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                DoMonitorWork();
            }
            catch (Exception ex)
            {
                ServiceLogManager.Instance.Error("数据监控出错：" + ex.Message);
                ServiceLogManager.Instance.Error(ex.StackTrace);
            }
        }

        private void Worker_Log_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                DoLogWork();
            }
            catch (Exception ex)
            {
                ServiceLogManager.Instance.Error("读取日志出错：" + ex.Message);
                ServiceLogManager.Instance.Error(ex.StackTrace);
            }
        }

        protected override void OnStart(string[] args)
        {
            //Debugger.Launch();
            ConfigFileHelper.Initialize();
            CommonPath.CreateMonitorConfigFile();
            CommonPath.CreateSerialPortConfigFile();
            SerialPortService.Instance.SaveSerialPortInfo();
            SerialPortService.Instance.StartMonitor();
            DoStart();
            ReadMonitorPara();
            if (CommonParas.Instance != null)
            {
                minitor_worker.RunWorkerAsync();
                //Debugger.Launch();
                ServiceLogManager.Instance.Info(CommonParas.Instance.ToString());
            }
            log_worker.RunWorkerAsync();
            StartCacheMonitor();
        }

        private void ReadMonitorPara()
        {
            using (FileStream fs = new FileStream(CommonPath.MonitorConfigFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (StreamReader reader = new StreamReader(fs))
                {
                    string val = reader.ReadLine();
                    if (string.IsNullOrWhiteSpace(val))
                    {
                        ServiceLogManager.Instance.Warning("监控未开启：未查询到监控参数。");
                    }
                    else
                    {
                        MonitorLimitPara para = JsonConvert.DeserializeObject<MonitorLimitPara>(val);
                        FileInfo info = new FileInfo(CommonPath.MonitorConfigFileName);
                        this.last_write_time = info.LastWriteTime;
                        if (para == null)
                        {
                            ServiceLogManager.Instance.Warning("未查询到监控参数。");
                        }
                        else
                        {
                            CommonParas.Instance.InitFrom(para);
                        }
                    }
                }
            }
        }

        private void UpdateMonitorPara()
        {           
            FileInfo info = new FileInfo(CommonPath.MonitorConfigFileName);
            if (info.LastWriteTime.Subtract(last_write_time).TotalSeconds > 0)
            {
                ReadMonitorPara();
            }
        }

        private void StartCacheMonitor()
        {
            CacheManager cacheManager = new CacheManager();
            _cacheManager = cacheManager;
            cacheManager.Start();
        }

        protected override void OnStop()
        {
            DoStop();
            SerialPortService.Instance.Disposed();
        }

        private void WriteToLog(string file_name, DateTime time)
        {
            try
            {
                int count = 0;
                using (FileStream fs = new FileStream(file_name, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
                {
                    foreach (var log in LogManager.Instance.GetLogsByTime(time))
                    {
                        string jsonString = JsonConvert.SerializeObject(log);
                        byte[] bytes = Encoding.UTF8.GetBytes(jsonString + Environment.NewLine);
                        fs.Write(bytes, 0, bytes.Length);
                        count++;
                    }
                }
                ServiceLogManager.Instance.Debug($"文件名称：{file_name}， 成功写入{count.ToString()}条日志。");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void DoSleep(int time_second)
        {
            int sleep_time = time_second;
            while ((!stop_sleep) && (sleep_time != 0))
            {
                Thread.Sleep(1000);
                sleep_time--;
            }
        }

        private void DoStop()
        {
            //Debugger.Launch();
            log_worker_running = false;
            if (stop_sleep == false)
            {
                stop_sleep = true;
            }
            monitor_worker_running = false;
            _cacheManager.Stop();
        }

        private void DoStart()
        {
            log_worker_running = true;
            if (stop_sleep == true)
            {
                stop_sleep = false;
            }
            monitor_worker_running = true;
        }

        private void DoLogWork()
        {
           // Debugger.Launch();           
            today_file = CommonPath.TodayFile;
            while (log_worker_running)
            {                   
                if (!today_file.Equals(CommonPath.TodayFile))
                {
                    WriteToLog(today_file, DateTime.Now.AddDays(-1));
                    today_file = CommonPath.TodayFile;
                    WriteToLog(today_file, DateTime.Now);
                }
                else
                {
                    DateTime time = DateTime.Now;
                    WriteToLog(today_file, time);
                    today_file = CommonPath.TodayFile;
                }
                DoSleep(3600);                
            }
        }

        private void DoMonitorWork()
        {
            MonitorLimitPara para = CommonParas.Instance;
            if (para != null)
            {
               
                NetMonitor netMonitor = new NetMonitor();
                netMonitor.NetChangedEventHandler += OnNetMonitorNetChangedEventHandler;
                netMonitor.Initialize();
               
                while (monitor_worker_running)
                {
                    UpdateMonitorPara();
                    if (para.EnableNetMonite)
                        netMonitor.DoMonitor();
                    else
                    {
                        netMonitor.Stop();
                    }                   

                    if (para.NeedGetCpuInfo())
                    {
                        CPUInfo cpuInfo = WindowsStateService.Monitor.ComputerInfo.GetCPUInfo();
                        if (cpuInfo != null)
                        {
                            if (para.EnableCpuTemperature)
                            {
                                if (cpuInfo.Temperature.HasValue)
                                {
                                    DataBase data = new DataBase(cpuInfo.Temperature.Value);
                                    WriteToMonitorFile(data, CommonPath.CpuTemperatureDatasFile);
                                }
                            }

                            if (para.EnableCpuUsage)
                            {
                                if (cpuInfo.Usage.HasValue)
                                {
                                    DataBase data = new DataBase(cpuInfo.Usage.Value);
                                    WriteToMonitorFile(data, CommonPath.CpuUsageDatasFile);
                                }
                            }
                        }
                    }
                    if (para.NeedGetMemoryInfo())
                    {
                        RAMInfo ramInfo = WindowsStateService.Monitor.ComputerInfo.GetRAMInfo();
                        if (ramInfo != null)
                        {
                            DataBase data = new DataBase(ramInfo.UsedMemoryRatio);
                            WriteToMonitorFile(data, CommonPath.UsedMemoryRatioDatasFile);
                        }
                    }

                    if (para.NeedGetDiskInfo())
                    {
                        DiskInfo diskInfo = WindowsStateService.Monitor.ComputerInfo.GetDiskInfo();
                        if (diskInfo != null)
                        {
                            if (para.EnableDiskTemperature)
                            {
                                if (diskInfo.Temperature.HasValue)
                                {
                                    DataBase data = new DataBase(diskInfo.Temperature.Value);
                                    WriteToMonitorFile(data, CommonPath.DiskTemperatureDatasFile);
                                }
                            }
                            if (para.EnableDiskUsage)
                            {
                                if (diskInfo.Usage.HasValue)
                                {
                                    DataBase data = new DataBase(diskInfo.Usage.Value);
                                    WriteToMonitorFile(data, CommonPath.DiskUsageDatasFile);
                                }
                            }
                        }
                    }

                    if(para.NeedGetMainBoardInfo())
                    {
                        MainBoardInfo mainBoardInfo = WindowsStateService.Monitor.ComputerInfo.GetMainBoardInfo();
                        if(mainBoardInfo != null)
                        {
                            if (para.EnableMainBoardTemperature)
                            {
                                if (mainBoardInfo.Temperature.HasValue)
                                {
                                    DataBase data = new DataBase(mainBoardInfo.Temperature.Value);
                                    WriteToMonitorFile(data, CommonPath.MainBoardTemperatureDatasFile);
                                }
                            }

                            if (para.EnableFanSpeed)
                            {
                                if (mainBoardInfo.FanSpeed.HasValue)
                                {
                                    DataBase data = new DataBase(mainBoardInfo.FanSpeed.Value);
                                    WriteToMonitorFile(data, CommonPath.FanSpeedDatasFile);
                                }
                            }
                        }
                    }
                    DoSleep(240);
                }

                if(netMonitor != null)
                {
                    netMonitor.NetChangedEventHandler -= OnNetMonitorNetChangedEventHandler;
                    netMonitor.Stop();
                }
            }
        }

        private void OnNetMonitorNetChangedEventHandler(object sender, NetEventArgs e)
        {        
            switch (e.EventType)
            {
                case NetEventType.NetInterfaceStatusChanged:
                    string msg = $"网络接口状态改变：ID：{e.NetId}    Name：{e.NetName}   Status：{e.Status.ToString()}";
                    //WriteToMonitorFile(data1, CommonPath.EthernetDatasFile);
                    if (e.Status == System.Net.NetworkInformation.OperationalStatus.Down)
                    {
                        ServiceLogManager.Instance.Error(msg);
                    }
                    else
                    {
                        ServiceLogManager.Instance.Info(msg);
                    }
                    break;
                case NetEventType.Error:
                    ServiceLogManager.Instance.Error(e.ErrorMsg);
                    break;
                case NetEventType.Normal:
                    DataBase data3 = new DataBase(e.ReceivedBytes);
                    WriteToMonitorFile(data3, CommonPath.GetReceivedPackageDatasFile(e.NetId));
                    DataBase data4 = new DataBase(e.SendBytes);
                    WriteToMonitorFile(data4, CommonPath.GetSendPackageDatasFile(e.NetId));
                    break;

            }
        }

        private void WriteToMonitorFile(DataBase data, string fileName)
        {
            if(data == null)
            {
                return;
            }
            string dataFile = fileName;
            using (FileStream fs = new FileStream(dataFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
            {
                string data_str = JsonConvert.SerializeObject(data);
                byte[] bytes = Encoding.UTF8.GetBytes(data_str + Environment.NewLine);
                fs.Write(bytes, 0, bytes.Length);
            }
        }
    }
}
